Skip to content

Phase 3: Security & admin test coverage (voters, auth, CRUD smoke, filters)#76

Open
turegjorup wants to merge 8 commits intodevelopfrom
feature/test-coverage-security
Open

Phase 3: Security & admin test coverage (voters, auth, CRUD smoke, filters)#76
turegjorup wants to merge 8 commits intodevelopfrom
feature/test-coverage-security

Conversation

@turegjorup
Copy link
Copy Markdown
Contributor

Summary

Second of four PRs in the test coverage plan. Follows PR #75 (Phase 1 — test infrastructure).

  • Voter unit tests: every significant branch of EventVoter, OrganizationVoter, LocationVoter, AddressVoter, TagVoter, UserActionVoter, UserEntityVoter.
  • Auth functional tests: login (valid/invalid/CSRF), anonymous redirect, registration including email-verification round-trip.
  • Dashboard role redirects: super-admin sees full menu; ROLE_EDITOR redirects to EventCrudController; ROLE_ORGANIZATION_EDITOR redirects to MyEventCrudController.
  • CRUD smoke + role gating: one test file per admin CRUD controller (13 total) asserting authorized roles get 200 and unauthorized get 302/403 with cross-org edit blocking on Event and Organization.
  • Filter tests: HasOrganizationFilter, JsonContainsFilter, and MyEventCrudController query-builder scoping.
  • Added lightweight TestEventFixtures (org-A/org-B/orphan events) to keep functional tests independent of the full EventFixture dependency chain.

Test infrastructure adjustments

  • config/packages/doctrine.yaml (when@test): dropped the _test dbname suffix — the db docker user lacks CREATE DATABASE privileges; DAMA transaction rollback already isolates tests on the shared dev schema.
  • config/packages/test/liip_test_fixtures.yaml: keep_database_and_schema: true — Liip now reuses the existing schema instead of drop+recreate.
  • config/services.yaml (when@test): registers App\Tests\Fixtures\* as doctrine.fixture.orm services so TestUserFixtures / TestEventFixtures load via Liip's DatabaseTool.
  • config/packages/web_profiler.yaml: profiler.collect: true in test env so MailerAssertionsTrait is wired.
  • AbstractAdminTestCase::adminUrl() now generates EasyAdmin pretty-URL routes (admin_<snake>_<action>) via the router, avoiding a 302 round-trip on every request.

Known production gap

OrganizationCrudController::configureActions() hides the "New" button for org-admins in the UI, but OrganizationVoter::supports() abstains when entity === null (the NEW action passes null). URL-level access to /admin/organization/new is therefore not enforced. One test (OrganizationCrudTest::testOrgAdminCannotCreateOrganization) is marked markTestSkipped() with the cause documented. Recommend a follow-up issue to fix OrganizationVoter to vote on NEW when entity is null.

Results

Tests: 125, Assertions: 239, Failures: 0, Errors: 0, Skipped: 1
  • Unit suite: 71 tests (22 pre-existing + 49 new across voter tests)
  • Functional suite: 54 tests (all new: auth + dashboard + CRUD + filter)

Test plan

  • vendor/bin/phpunit — 125 passing, 1 documented skip
  • vendor/bin/phpstan analyse — clean
  • composer run coding-standards-check — clean
  • markdownlint '**/*.md' — clean
  • CI green on this PR

Next: feature/test-coverage-pipeline (Phase 2) is already committed locally; PR opens after this one lands.

🤖 Generated with Claude Code

turegjorup and others added 7 commits April 20, 2026 11:18
Cover voter authorization branches, EasyAdmin CRUD smoke, auth flows
and filter behavior so regressions in access control surface in CI
without requiring a full environment exercise.

- Unit tests for every voter in App\Security\Voter (EventVoter covers
  feed-lock, role hierarchy and organization membership; remaining
  voters cover their significant branches).
- Functional tests for login, authorization and registration incl.
  email verification round-trip.
- Dashboard role redirects and CRUD smoke per controller, including
  cross-org edit blocking on Event and Organization.
- Filter tests for HasOrganizationFilter, JsonContainsFilter and the
  MyEventCrudController scoping query builder.
- Lightweight TestEventFixtures keeps functional tests independent of
  the full EventFixture dependency chain.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Drop the _test dbname suffix: the `db` docker user lacks CREATE DATABASE
  privileges, and DAMA's transaction rollback already isolates tests on
  the shared dev schema.
- Tell Liip to keep the existing DB/schema rather than drop+recreate per
  test (the drop path was hitting "A database is required").
- Register App\Tests\Fixtures\ as Doctrine fixture services in the test
  environment so TestUserFixtures and TestEventFixtures can be loaded
  through Liip's DatabaseTool.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
`AbstractAdminTestCase::adminUrl()` now uses the EasyAdmin-generated
`admin_<snake>_<action>` route names, so the test client lands directly
on the CRUD page instead of following a 302 from the legacy query-string
form. This unblocks most functional CRUD tests that were asserting 200
on the dashboard URL and getting a redirect to the pretty URL.

Additionally, the test-only profiler config now sets `collect: true`
(rather than `false`) so `MailerAssertionsTrait::assertQueuedEmailCount`
can read the message logger events via `profiler.is_disabled_state_checker`.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Dashboard assertions look for translated Danish labels (Alt indhold,
  Brugere, Feeds) because templates render with the default locale.
- HasOrganizationFilter uses the BooleanFilterType form, whose query
  parameter is `filters[hasOrganization]`, not the comparison/value
  structure.
- AuthorizationTest normalises the redirect Location to a path before
  checking the `/admin` prefix (the header is an absolute URL).
- Registration form tests use the translated submit button label and
  valid email addresses; the user lookup after redirect avoids a stale
  EM reference, and the outbound email is asserted as queued (mailer is
  routed through the async Messenger transport).
- OrganizationCrudTest skips `testOrgAdminCannotCreateOrganization` with
  a clear note: the OrganizationVoter only fires when an entity instance
  is present, and EasyAdmin invokes EA_EXECUTE_ACTION with a null entity
  for the NEW action, so URL-level access is not currently enforced.
- Minor php-cs-fixer tidy on EventVoterTest (trailing blank line).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
PHPUnit 12 emits a notice for every createMock() call that has no
expectations attached. Voter tests only need stubbing behaviour
(willReturn callbacks, no assertion on call counts), so createStub is
the correct primitive. Swapping across all voter tests eliminates the
49 PHPUnit notices that appeared under the previous commit.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Functional tests need the DB schema in place. Locally the dev schema
already exists; in CI the mariadb container starts empty, so Liip's
purger hits a missing vocabulary_tag table. Adding a migrate step
before task test brings CI in line with local.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@codecov-commenter
Copy link
Copy Markdown

codecov-commenter commented Apr 20, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 34.58%. Comparing base (bcfcd2c) to head (8f2b007).
⚠️ Report is 21 commits behind head on develop.

Additional details and impacted files
@@              Coverage Diff               @@
##             develop      #76       +/-   ##
==============================================
+ Coverage       3.70%   34.58%   +30.87%     
- Complexity      1251     1262       +11     
==============================================
  Files            162      162               
  Lines           4448     4450        +2     
==============================================
+ Hits             165     1539     +1374     
+ Misses          4283     2911     -1372     
Flag Coverage Δ
unittests 34.58% <ø> (+30.87%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants